# Отказоустойчивость

В этом разделе мы обсудим отказоустойчивость в мире микросервисов.
Мы посмотрим, какие решения, прозрачные для приложений, предлагает нам Istio.
А так же, как мы могли бы реализовать отказоустойчивость в нашем приложении.

Чтобы не запутаться в разных версиях coffee-shop `v1` и` v2`, давайте сначала вернемся к исходному состоянию и будем работать только с subset `v1`.  

Таким образом мы должны поменять Virtual Service, Destination Rule в исходное состояние (`kubectl apply`) и удалить Deployment `coffee-shop-v2` (`kubectl delete deployment coffee-shop-v2`). 

После того как Deployment будет удален, Pod-ы версии 2 так же будут удалены автоматически.

> **Причмечание**
>
>Несмотря на то что мы можем поменять содержимое файлов конфигурации инфраструктуры и применить их через `kubectl apply`, Kubernetes не сможет отследить удаление ресурсов в файлах, поскольку он только создает и обновляет конфигурации указанных ресусрсов.
>Таким образом нам нужно явно `kubectl delete` ненужные ресурсы.


# Функционал для отказоустойчивости

Istio включает различный функционал для обеспечения отказоусточивости сервисов, например такой как, timeout, circuit breaker, retry.

Поскольку sidecar прокси Istio перехватывают все входящие и исходяшие подключения от  приложения, то это означает, что если, например, наше приложение не поддерживает timeout соединения, то  Istio сможет это обеспечить без изменения кода приложения.

# Timeout

Istio позволяет установить timeout на уровне правил маршрутизации Virtual Service.

Давайте добавим timeout 1 секунда для соединений от лица coffee-shop сервиса и применим обновленный Virtual Service на нашем кластере:

```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: coffee-shop
spec:
  hosts:
  - "*"
  gateways:
  - coffee-shop-gateway
  http:
  - route:
    - destination:
        host: coffee-shop
        port:
          number: 9080
        subset: v1
    timeout: 1s
```

>**Примечание**
>
>Определение `timeout` содержится в специальном YAML объекте `route`.

Теперь общее время запросов за кофе не будет превышать одну секунду иначе sidecar прокси будет возврашать HTTP ошибку.


# Тестирование отказоустойчивости

Наше приложение всегда отвечает на запросы не дольше одной секунды. Однако нам надо убедиться, действительно ли наши изменения применились так как надо.
Как же тогда проверить приложение на timeout?

К счастью, в Istio есть функционал позволяющий создавать исключительные ситуации  для тестирования отказоустойчивости приложений.

Для этого у sidecar-ов есть два способа: добавление `искусственных задержек` и `сбой запросов`.
Мы можем добвить в правила маршрутизации эти исключителные ситуации для определенного процента запросов.

Мы можем поменять Virtual Service для сервиса `barista` добавив 3 секундную задержку для 50% запросов:

```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: barista
spec:
  hosts:
  - barista
  http:
  - route:
    - destination:
        host: barista
        subset: v1
    fault:
      delay:
        fixedDelay: 3s
        percent: 50
```

Если мы применим изменения к нашему кластеру, то увидем что некотороые запросы к нашему приложению будут заканчиваться ошибками спустя примерно одну секунду.
Мы не увидем ни одного запроса, который будет длиться 3 секунды, из-за timeout для соединений от coffee-shop в 1 секунду, определенному в правилах маршрутизации этого сервиса. 

```
while true; do
curl <ip-address>:<node-port>/coffee-shop/resources/orders -i -XPOST \
  -H 'Content-Type: application/json' \
  -d '{"type":"Espresso"}' \
  | grep HTTP
sleep 1
done
```

>**Примечание**
>
>Параметер `fault` предназначен только для целей тестирования. Не применяйте его в продуктивных средах, чтобы избежать непроизвольного замедления или сбоев соединений.

Помимо наблюдения за откликами от приложения, мы можем использовать инструменты  визуализации телеметрии Istio.
Обратите внимание на дашборды Grafana и Jaeger трасировки, чтобы увидеть запросы, которые закончились с ошибкой. 

Данная лабораторная работа охватывает только timeout-ы и простые ошибки, но Istio так же предоставляет функциональность для повтров запросов, circuit breaker-ы и др. 
Чтобы узнать по больше ознакомтесь с [документацией](https://istio.io/docs/tasks/traffic-management/).


# Уровень приложения

Создание отказоустойчивого микросервиса является ключевым моментом при разработке микросервисов.
Помимо отказоустойчивости на уровне инфраструктуры, иногда требуется более тонкая отказоустойчивость на уровне приложения.

[MicroProfile Fault Tolerance](https://github.com/eclipse/microprofile-fault-tolerance/) предоставляет простое, но кастомизируемое решение на уровне приложения для обеспечения отказоустойчивости.
Он предлагает следующие возможности: timeout, retry, bulkhead, circuit breaker и fallback.

В целом, отказоустойчивость реализованная на уровне приложения является более кастомизируемой и тонкой в настройке, тогда как на уровне Istio имеет фиксированный набор параметров и простоту в настройке без модификации приложения.

Как рекомендация, в комплексных задачах для обеспечения отказоустойчивости можно использовать MicroProfile совместно с Istio.

Похоже что мы закончили последний раздел! [Заключение](08-conclusion.md).
